﻿#pragma once
#define TAG "ASYNC_FUTURE"

#ifndef ARD_ASYNCFUTURE_H
#define ARD_ASYNCFUTURE_H

#include <Common.h>


 /*在C++中，Boost.Coroutine库提供了有栈协程的支持，而C++20标准引入的协程则被设计为无栈协程。
 
 有栈协程，也称为堆栈协程，每个协程都有自己的堆栈空间，可以保存局部变量和调用栈。这意味着有栈协程可以在任何函数调用深度挂起，并在稍后从同一点恢复执行。有栈协程的这种特性使得它们在编程模型上更接近于传统的线程。
 无栈协程，顾名思义，不保持自己的堆栈。它们通常在单个堆栈上运行，并使用特殊的控制结构（如生成器或迭代器）来保存和恢复状态。无栈协程通常只能在顶层函数挂起和恢复，不能在嵌套的函数调用中挂起。

 有栈协程:可以在任意函数调用深度挂起和恢复。编程模型更加直观，类似于多线程编程。
 无栈协程:内存消耗较低，因为不需要为每个协程分配堆栈空间。上下文切换开销较小，因为不需要保存和恢复堆栈。
 
 有栈协程:每个协程需要单独的堆栈空间，这可能会导致较高的内存消耗。换协程可能涉及到堆栈的保存和恢复，可能会有一定的性能开销。
 无栈协程:编程模型可能不如有栈协程直观，因为不能在任意深度的函数调用中挂起。可能需要特殊的语言支持或库来实现。

 <summary>
 创建：当调用一个协程函数时，它并不立即执行，而是创建一个协程对象，并返回一个与协程相关联的对象（通常是由协程承诺类型定义的）。
 暂停：协程可以通过co_await和co_yield关键字暂停执行。co_await用于等待异步操作完成，而co_yield用于生成序列中的下一个值。
 恢复：协程可以通过调用协程句柄的resume方法恢复执行。
 结束：协程可以通过co_return结束执行，或者到达函数的末尾自动结束。结束时，协程承诺对象会处理返回值或者清理资源。
 销毁：协程的调用者可以通过调用协程句柄的destroy方法销毁协程，释放其资源。
 
 co_await：用于挂起协程的执行，直到等待的对象（通常是一个future或类似的异步结果）变得可用。
 co_return：用于指示协程返回某个值并终止其执行。
 co_yield：用于在生成器协程中产生一个值，然后挂起协程的执行，允许调用者继续执行。
 </summary>*/

//使用这个作为返回值以及在函数中添加co_的关键词,函数就会被标记,运行顺序get_return_object->initial_suspend->func->final_suspend...
struct AsyncFuture
{
    struct promise_type
    {
        bool value; // 存储协程返回的值

        //协程开始时立即暂停 这些函数控制协程的开始和结束时是否应该立即挂起。
        //在协程首次启动前调用。如果返回 std::suspend_always，协程将在启动后立即挂起，直到外部显示地恢复执行（例如通过调用 resume 方法）
        std::suspend_always initial_suspend() {
            LogD("AsyncExam inital_suspend!");
            return {};
        }

        //协程开始时立即暂停 这些函数控制协程的开始和结束时是否应该立即挂起。
        //在协程准备完成执行时调用。返回 std::suspend_always 意味着即使协程运行到尾部，也会挂起，防止协程立即被销毁。
        auto final_suspend() noexcept {
            LogD("AsyncExam final_suspend!");
            return std::suspend_always{};
        }

        // 这个函数用于处理协程内部抛出的未处理异常。
        void unhandled_exception() {
            LogD("AsyncExam unhandled_exception!");
            std::terminate();
        }

        // 获取与协程关联的返回对象 当协程开始时，这个函数被调用来获取与协程关联的返回对象。
        AsyncFuture get_return_object() {
            LogD("AsyncExam get_return_object!");
            return AsyncFuture{
                std::coroutine_handle<promise_type>::from_promise(*this)
            };
        }

        // 通过co_return返回值时调用 void return_void() {} 二选一
        void return_value(bool v) {
            LogD("AsyncExam return_value!");
            value = std::move(v);
        }

        // 通过co_yield关键字调用，用于挂起协程并返回当前行
        //在协程中通过 co_yield 表达式调用。在这里返回 std::suspend_always 表示每次 co_yield 后协程都会挂起等待外部的恢复
        auto yield_value(const bool line) {
            value = line;
            return std::suspend_always{};
        }
    };
    // 协程句柄，用于控制协程的执行
    std::coroutine_handle<promise_type> h;
    // 构造函数，接收协程句柄
    AsyncFuture(std::coroutine_handle<promise_type> h) : h(h) {}
    // 析构函数，销毁协程
    ~AsyncFuture() { h.destroy(); }
    // 获取协程的返回值
    bool get() {
        //h.resume(); // 恢复协程的执行
        return h.promise().value; // 返回协程的结果
    }
};

#endif // !ARD_ASYNCFUTURE_H
